// 辅助函数:将值限制在指定范围内
const clamp = (value, min, max) => Math.max(min, Math.min(max, value))

// 辅助函数:将十六进制转为RGB
function hexToRgb(hex) {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null
}

// RGB转HSL
function rgbToHsl(r, g, b) {
    r /= 255
    g /= 255
    b /= 255

    const max = Math.max(r, g, b)
    const min = Math.min(r, g, b)

    // 分开声明变量
    let h = 0
    let s = 0
    const l = (max + min) / 2

    if (max !== min) {
        const d = max - min
        s = l > 0.5 ? d / (2 - max - min) : d / (max + min)

        switch (max) {
            case r:
                h = (g - b) / d + (g < b ? 6 : 0)
                break
            case g:
                h = (b - r) / d + 2
                break
            case b:
                h = (r - g) / d + 4
                break
        }
        h /= 6
    }

    return {
        h: h * 360,
        s: s * 100,
        l: l * 100
    }
}

// HSL转RGB
function hslToRgb(h, s, l) {
    h /= 360
    s /= 100
    l /= 100

    let r, g, b

    if (s === 0) {
        r = g = b = l
    } else {
        const hue2rgb = (p, q, t) => {
            if (t < 0) t += 1
            if (t > 1) t -= 1
            if (t < 1 / 6) return p + (q - p) * 6 * t
            if (t < 1 / 2) return q
            if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
            return p
        }

        const q = l < 0.5 ? l * (1 + s) : l + s - l * s
        const p = 2 * l - q

        r = hue2rgb(p, q, h + 1 / 3)
        g = hue2rgb(p, q, h)
        b = hue2rgb(p, q, h - 1 / 3)
    }

    return {
        r: Math.round(r * 255),
        g: Math.round(g * 255),
        b: Math.round(b * 255)
    }
}

// RGB转十六进制
function rgbToHex(r, g, b) {
    return '#' + [r, g, b].map(x => {
        const hex = x.toString(16)
        return hex.length === 1 ? '0' + hex : hex
    }).join('')
}


/**
 * 按比例调整颜色值 (对应 SASS color.scale())
 * @param {string} color - 输入的颜色值,支持十六进制格式 (例如: '#ff0000')
 * @param {Object} options - 参数
 * @param {number} [options.$hue=0] - 色相调整比例,范围[-1,1]
 *                                    -1 表示减少360度
 *                                     0 表示不变
 *                                     1 表示增加360度
 * @param {number} [options.$saturation=0] - 饱和度调整比例,范围[-1,1]
 *                                          -1 表示降低100%
 *                                           0 表示不变
 *                                           1 表示提高100%
 * @param {number} [options.$lightness=0] - 亮度调整比例,范围[-1,1]
 *                                         -1 表示降低100%
 *                                          0 表示不变
 *                                          1 表示提高100%
 * @returns {string} 返回调整后的十六进制颜色值
 */
export function colorScale(color, {
    $hue = 0,
    $saturation = 0,
    $lightness = 0
} = {}) {
    const rgb = hexToRgb(color)
    if (!rgb) throw new Error('Invalid color')

    const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b)

    // 使用比例调整
    if ($hue) {
        const scale = clamp($hue, -1, 1)
        hsl.h = clamp(hsl.h + (360 * scale), 0, 360)
    }

    if ($saturation) {
        const scale = clamp($saturation, -1, 1)
        hsl.s = clamp(hsl.s * (1 + scale), 0, 100)
    }

    if ($lightness) {
        const scale = clamp($lightness, -1, 1)
        hsl.l = clamp(hsl.l * (1 + scale), 0, 100)
    }

    const newRgb = hslToRgb(hsl.h, hsl.s, hsl.l)
    return rgbToHex(newRgb.r, newRgb.g, newRgb.b)
}

/**
 * 设置具体的颜色值 (对应 SASS color.change())
 * @param {string} color - 输入的颜色值,支持十六进制格式 (例如: '#ff0000')
 * @param {Object} options - 参数
 * @param {number} [options.$hue] - 色相值,范围[0,360]
 *                                  0/360 = 红色
 *                                  120 = 绿色
 *                                  240 = 蓝色
 * @param {number} [options.$saturation] - 饱和度值,范围[0,100]
 *                                        0 = 灰色
 *                                        100 = 完全饱和
 * @param {number} [options.$lightness] - 亮度值,范围[0,100]
 *                                       0 = 黑色
 *                                       50 = 正常亮度
 *                                       100 = 白色
 * @returns {string} 返回调整后的十六进制颜色值
 */
export function colorChange(color, {
    $hue,
    $saturation,
    $lightness
} = {}) {
    const rgb = hexToRgb(color)
    if (!rgb) throw new Error('Invalid color')

    const hsl = rgbToHsl(rgb.r, rgb.g, rgb.b)

    // 直接设置新值
    if ($hue !== undefined) {
        hsl.h = clamp($hue, 0, 360)
    }

    if ($saturation !== undefined) {
        hsl.s = clamp($saturation, 0, 100)
    }

    if ($lightness !== undefined) {
        hsl.l = clamp($lightness, 0, 100)
    }

    const newRgb = hslToRgb(hsl.h, hsl.s, hsl.l)
    return rgbToHex(newRgb.r, newRgb.g, newRgb.b)
}

/**
 * 调整RGB颜色通道值
 * @param {string} color - 输入的颜色值,支持十六进制格式 (例如: '#ff0000')
 * @param {Object} options - 参数
 * @param {number} [options.$red=0] - 红色通道调整值,范围[-255,255]
 *                                   负值减少红色分量
 *                                   正值增加红色分量
 * @param {number} [options.$green=0] - 绿色通道调整值,范围[-255,255]
 *                                     负值减少绿色分量
 *                                     正值增加绿色分量
 * @param {number} [options.$blue=0] - 蓝色通道调整值,范围[-255,255]
 *                                    负值减少蓝色分量
 *                                    正值增加蓝色分量
 * @returns {string} 返回调整后的十六进制颜色值
 */
export function colorAdjustRGB(color, {
    $red = 0,
    $green = 0,
    $blue = 0
} = {}) {
    const rgb = hexToRgb(color)
    if (!rgb) throw new Error('Invalid color')

    const newRgb = {
        r: clamp(rgb.r + $red, 0, 255),
        g: clamp(rgb.g + $green, 0, 255),
        b: clamp(rgb.b + $blue, 0, 255)
    }

    return rgbToHex(newRgb.r, newRgb.g, newRgb.b)
}
